home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- * $Id: listdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $
- *
- *. Copyright(c) 1993,1994 by T.C. Zhao
- * All rights reserved.
- *.
- *
- * Semi-portable directory reader with cache. All entries will be put
- * into a structure list whose members are name and type.
- ***********************************************************************/
- #if !defined(lint) && defined(F_ID)
- char *id_dlist = "$Id: listdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $";
- #endif
-
- #include <stdio.h>
- #include <string.h>
- #include <malloc.h>
- #include <limits.h>
- #include "ulib.h"
-
- #ifndef PATH_MAX
- #define PATH_MAX 1024
- #endif
-
- #define FLEN_MAX 256 /* maximum filename length w/o directory */
-
-
- /******************************************************************
- * Read a directory on UNIX SysV like systems
- *
- *******************************************************************/
-
- #include "unistd.h"
- #include <sys/types.h>
- #include <dirent.h>
- #include <sys/stat.h>
-
- /** On Ultrix, scandir and alphasort are never decleard */
- #if defined(__STRICT_ANSI__)
-
- extern int scandir(const char *dir, struct dirent **[],
- int (*select) (struct dirent *),
- int (*howsort) (struct dirent **, struct dirent **));
- extern int alphasort(struct dirent **, struct dirent **);
- #endif /** GCC on Ultrix */
-
- #define MAXFL (PATH_MAX + FLEN_MAX)
-
- static const char *cpat; /* current pattern */
- static const char *cdir; /* current working directory */
- static char fname[MAXFL + 2];
- static struct stat ffstat;
-
- /******************************************************************
- * Filter the filename before handing over to the "file is here" list
- ******************************************************************/
- static int
- SysV_fselect(struct dirent *f)
- {
- strcat(strcpy(fname, cdir), f->d_name);
- stat(fname, &ffstat);
- /* always keep directory */
- return (ffstat.st_mode & S_IFDIR) || wildmat(f->d_name, cpat);
- }
-
-
- /*******************************************************************
- * On entry, dir must be no zero and be terminated properly, i.e.,
- * ends with /
- *******************************************************************/
-
- #ifndef M_DBG
- #define Tfree free
- #endif
-
- static int
- SysV_get_entries(const char *dir, const char *pat, Dirlist ** dirlist)
- {
- static struct dirent **dlist;
- Dirlist *dl;
- static int lastn;
-
- cpat = pat;
- cdir = dir;
-
- /* free all memory used. If malloc wrapper is used, need to change Tfree */
- if (dlist)
- {
- while (--lastn >= 0)
- if (dlist[lastn])
- Tfree(dlist[lastn]);
- Tfree(dlist);
- dlist = 0;
- }
-
- /** read dir */
- if ((lastn = scandir(dir, &dlist, SysV_fselect, alphasort)) > 0)
- {
- int i;
- unsigned long mode;
-
- dl = *dirlist = (Dirlist *) malloc((lastn + 1) * sizeof(Dirlist));
-
- for (i = 0; i < lastn; i++, dl++)
- {
- strcat(strcpy(fname, dir), dlist[i]->d_name);
- stat(fname, &ffstat);
- mode = ffstat.st_mode;
- dl->name = strdup(dlist[i]->d_name);
- dl->type = ((mode & S_IFDIR) == S_IFDIR) ? FT_DIR :
- (((mode & S_IFREG) == S_IFREG) ? FT_FILE : FT_OTHER);
- }
- dl->name = 0; /* sentinel */
- }
- return lastn;
- }
-
-
- /********************************************************************
- * The user routine.
- *
- * Get a list of files in directory, subject to pattern matching,
- * and return the file list. Rescan will force a read even the requested
- * directory is cached.
- *
- ********************************************************************/
-
- #define MAXCACHE 10
-
- static char *lastdir[MAXCACHE], *lastpat[MAXCACHE];
- static int lastn[MAXCACHE];
- static Dirlist *dirlist[MAXCACHE];
-
- /********************************************************************
- * Check if a particular directory is cached
- ********************************************************************/
- static int
- is_cached(const char *dir, const char *pat, int *c)
- {
- int cached = 0, i = 0;
- static int lastcache;
-
- do
- {
- cached = lastpat[i] && lastdir[i] &&
- strcmp(lastdir[i], dir) == 0 && strcmp(lastpat[i], pat) == 0 &&
- (dirlist[i] && dirlist[i]->name);
-
- *c = i++;
- }
- while (!cached && i < MAXCACHE);
-
- /* search for the least used slot if not cached */
- if (!cached)
- *c = (++lastcache) % MAXCACHE;
-
- lastcache = *c;
- M_info("CheckDirCache", "%s is %s cached", dir, cached ? "" : "not");
- return cached;
- }
-
- static void
- free_dirlist(Dirlist * dl)
- {
-
- while (dl && dl->name)
- {
- free(dl->name);
- dl->name = 0; /* important: signifies empty list */
- dl++;
- }
- }
-
- void
- free_all_dirlist(void)
- {
- int i;
-
- for (i = 0; i < MAXCACHE; i++)
- {
- free_dirlist(dirlist[i]);
- dirlist[i] = 0;
- }
- }
-
-
- /**********************************************************************
- * The user callable routine to read a directory
- *********************************************************************/
-
- Dirlist *
- get_dir_list(const char *dir, const char *pattern, int *n, int rescan)
- {
- int i, c;
- const char *pat = pattern;
- static char okdir[PATH_MAX + 1];
-
- if (!dir || !*dir)
- return 0;
-
- if (!pat || !*pat)
- pat = "*";
-
- /* fix the directory on the fly */
- i = strlen(strcpy(okdir, dir));
- if (okdir[i - 1] != '/')
- {
- okdir[i] = '/';
- okdir[++i] = '\0';
- }
-
-
- /* is_cached must go first to get correct cache location */
- if (!is_cached(okdir, pat, &c) || rescan)
- {
- free_dirlist(dirlist[c]);
- dirlist[c] = 0;
- lastn[c] = SysV_get_entries(okdir, pat, &dirlist[c]);
- StrReDup(lastpat[c], pat);
- StrReDup(lastdir[c], okdir);
- }
-
- *n = lastn[c];
- return dirlist[c];
- }
-
-
-
- /***********************************************************************
- * Misc. routines related directory
- **********************************************************************/
- int
- is_valid_dir(const char *name)
- {
- struct stat statbuf;
-
- return (stat(name, &statbuf) == 0 &&
- (statbuf.st_mode & S_IFDIR) == S_IFDIR);
- }
-
- /************************************************************************
- * Remove all files, except directories from dir
- ***********************************************************************/
- void
- rm_all_files(const char *dir, const char *pat)
- {
- Dirlist *dl, *dls;
- int n;
-
- push_dir();
- chdir(dir);
-
- /* always re-read the directory entries */
- dl = get_dir_list(dir, pat, &n, 1);
-
- if (dl && n > 0)
- {
- for (dls = dl + n; --dls >= dl;)
- {
- if (dls->type == FT_FILE)
- if (remove(dls->name))
- perror(dls->name);
- }
- }
- pop_dir();
- free_dirlist(dl);
- }
-
- /************************************************************
- * File modification time
- ***********************************************************/
- unsigned long
- f_mtime(const char *s)
- {
- struct stat fffstat;
- stat(s, &fffstat);
- return fffstat.st_mtime;
- }
-